/******************************************************************************
 * Copyright (C) 2015  671643387@qq.com
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
 *****************************************************************************/

#ifndef NODECPP_DATA_REL_CALLBACKS_H_
#define NODECPP_DATA_REL_CALLBACKS_H_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

namespace NodeCpp {
namespace Data {
namespace Rel {
    class QueryResult;

    template<class Class, typename ParamType1, typename ParamType2>
    class _Callback
    {
    protected:
        typedef void (Class::*Method)(ParamType1, ParamType2);
        Class* Object_;
        Method Method_;
        ParamType1 Param1_;
        ParamType2 Param2_;
        void _Execute(void) { (Object_->*Method_)(Param1_, Param2_); }

    public:
        _Callback(Class* _Object, Method _Method, ParamType1 _Param1, ParamType2 _Param2)
            : Object_(_Object), Method_(_Method),
            Param1_(_Param1), Param2_(_Param2)
        {
        }

        _Callback(_Callback<Class, ParamType1, ParamType2> const& _CB)
            : Object_(_CB.Object_), Method_(_CB.Method_),
            Param1_(_CB.Param1_), Param2_(_CB.Param2_)
        {
        }
    };

    class IQueryCallback
    {
    public:
        virtual void Execute(void) = 0;
        virtual ~IQueryCallback(void) {}

        virtual void SetResult(QueryResult* _Result) = 0;
        virtual QueryResult* GetResult(void) = 0;
    };

    template<class CB>
    class _IQueryCallback : public CB, public IQueryCallback
    {
    public:
        _IQueryCallback(CB const& _CB) : CB(_CB)
        {
        }

        void Execute(void) { CB::_Execute(); }
        void SetResult(QueryResult* _Result) { CB::Param1_ = _Result; }
        QueryResult* GetResult(void) { return CB::Param1_; }
    };

    template<class Class, typename ParamType1>
    class QueryCallback : public _IQueryCallback<_Callback<Class, QueryResult*, ParamType1> >
    {
    private:
        typedef _Callback<Class, QueryResult*, ParamType1> QC1;

    public:
        QueryCallback(Class* _Object, typename QC1::Method _Method, QueryResult* _Result, ParamType1 _Param1)
            : _IQueryCallback<QC1>(QC1(_Object, _Method, _Result, _Param1))
        {
        }
    };

}}}

#endif // NODECPP_DATA_REL_CALLBACKS_H_
